{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Explore a Global News Media Dataset using Jupyter Widgets \n",
    "\n",
    "#### Objective: Use the Descartes Labs Vectors Service to query the Global Database of Events, Language and Tone (GDELT Project) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial demonstrates loading data through the Vectors Service and plotting it in an embedded map powered by Jupyter Widgets and ipyleaflet. To learn more about GDELT, visit: https://www.gdeltproject.org/ It is worth noting the GDELT dataset loaded for this example is only a single snap-shot in time and is not regularly updated. To learn more about ipyleaflet, visit: https://ipyleaflet.readthedocs.io/en/latest/api_reference/widget_control.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ipyleaflet import Map, basemaps, basemap_to_tiles, TileLayer, DrawControl, \\\n",
    "    SplitMapControl, FullScreenControl, GeoJSON, WidgetControl\n",
    "from ipywidgets import HTML\n",
    "import ipywidgets as w\n",
    "from ipyleaflet import DrawControl, SplitMapControl, FullScreenControl, LayersControl, Marker, MarkerCluster\n",
    "from descarteslabs import Raster\n",
    "import descarteslabs as dl\n",
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, we prepare two tiled layers for the map background using the Descartes Labs tiles endpoint. One true color composite and one NDVI composite.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "tiles = Raster(\"https://platform.descarteslabs.com/tiles/v2/\")\n",
    "\n",
    "before_options = {\"products\":[\"sentinel-2:L1C\"],\n",
    "           \"bands\":[\"red\",\"green\",\"blue\",\"alpha\"],\n",
    "           \"scales\":[[0,4000],[0,4000],[0,4000],[0,1]],\n",
    "           \"start_time\":\"2019-03-18T00:00:00Z\",\n",
    "           \"end_time\":\"2019-03-29T00:00:00Z\",\n",
    "           \"date\":\"acquired\",\n",
    "           \"processing_level\":\"toa\"}\n",
    "\n",
    "after_options = {\"products\":[\"sentinel-2:L1C\"],\n",
    "           \"bands\":[\"ndvi\",\"alpha\"],\n",
    "           \"scales\":[[32768,65535],[0,1]],\n",
    "           \"start_time\":\"2019-03-18T00:00:00Z\",\n",
    "           \"end_time\":\"2019-03-29T00:00:00Z\",\n",
    "           \"date\":\"acquired\",\n",
    "           \"processing_level\":\"toa\"}\n",
    "\n",
    "before_tile = TileLayer()\n",
    "before_tile.url = tiles.session.post(\"xyz\", json=before_options).json()['url']\n",
    "before_tile.name = \"RGB\"\n",
    "\n",
    "after_tile = TileLayer()\n",
    "after_tile.url = tiles.session.post(\"xyz\", json=after_options).json()['url']\n",
    "after_tile.name = \"NDVI\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we create a function that allows you to query the GDELT dataset based on the ipyleaflet map's viewport. The function renders the returned data points on the embedded map that display articles once run.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a48d66aace3046eeb3700fe4413f2124",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output(layout=Layout(border='1px solid black'))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "layers = {}\n",
    "current_features = []\n",
    "clicked = []\n",
    "debug_view = w.Output(layout={'border': '1px solid black'})\n",
    "current_features = []\n",
    "\n",
    "@debug_view.capture(clear_output=True)\n",
    "def load_gdelt(*args, **kwargs):\n",
    "    clicked.append((args, kwargs))\n",
    "    print(\"clicked\")\n",
    "    clicked.append(m)\n",
    "\n",
    "    fc = dl.vectors.FeatureCollection(\"1be52be97ed54c22bfc3a09f4b64155\")\n",
    "    fc.filter(geometry=m.bounds_polygon)\n",
    "    bound_geom = [list(p)[::-1] for p in m.bounds_polygon[::-1]]\n",
    "    bound_geom.append(bound_geom[0])    \n",
    "    geom_json = {'type':'Polygon', 'coordinates':[bound_geom]}\n",
    "    print(\"about to query\")\n",
    "    \n",
    "    markers = []\n",
    "    t1 = -time.time()\n",
    "    for FF in fc.filter(geometry=geom_json).limit(100).features():\n",
    "        f = FF.geojson\n",
    "        marker = Marker(location=f['geometry']['coordinates'][::-1])\n",
    "        popup = HTML()\n",
    "        url = f['properties']['SOURCEURL']\n",
    "        popup.value = \"\"\"<a href={} target=\"_blank\">{}</a>\"\"\".format(url, url)\n",
    "        marker.popup = popup\n",
    "        markers.append(marker)\n",
    "        current_features.append(f) \n",
    "    t1 += time.time()\n",
    "    print(\"gathered features in {}\".format(t1))\n",
    "\n",
    "    marker_cluster = MarkerCluster(markers=markers)\n",
    "    \n",
    "    m.add_layer(marker_cluster)\n",
    "    layers['gdelt'] = marker_cluster\n",
    "    clicked.append(\"4\")\n",
    "    \n",
    "button = w.Button(\n",
    "    description='Search GDELT',\n",
    "    disabled=False,\n",
    "    button_style='', # 'success', 'info', 'warning', 'danger' or ''\n",
    "    tooltip='Search',\n",
    ")\n",
    "button.on_click(load_gdelt)\n",
    "wc = WidgetControl(widget = button, position='bottomright')\n",
    "\n",
    "debug_view"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The next code block renders the ipyleaflet map with the tiled layers we defined above. You can toggle between the true color composite, NDVI composite, and a base map using the layer drop-down in the top right hand corner. You can expand the view to the full extent of the screen using the expand button in the bottom right hand corner. \n",
    "\n",
    "After running the code block, set the view port to represent your area of interest. Scroll to the bottom of the embedded map and click \"Search GDELT\". "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b2e18500203141b9aabc3e95321a6f1f",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Map(basemap={'url': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 'max_zoom': 19, 'attribution': 'Map …"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "m = Map(center=(35.6824, -105.581), zoom=9, scroll_wheel_zoom=True, min_zoom=4)\n",
    "m.add_layer(before_tile)\n",
    "m.add_layer(after_tile)\n",
    "\n",
    "m.layout.height = '600px'\n",
    "\n",
    "draw_control = DrawControl()\n",
    "m.add_control(draw_control)\n",
    "m.add_control(FullScreenControl())\n",
    "m.add_control(LayersControl())\n",
    "\n",
    "draw_events = []\n",
    "\n",
    "@debug_view.capture(clear_output=True)\n",
    "def callback(*args, **kwargs):\n",
    "    draw_events.append(kwargs['geo_json'])\n",
    "    \n",
    "    \n",
    "draw_control.on_draw(callback)\n",
    "\n",
    "m.add_control(wc)\n",
    "m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "draw_events"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "rice-stats",
   "language": "python",
   "name": "rice-stats"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
